/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * EnvironmentFrame.java
 *
 * Created on 2012-01-02, 19:53:02
 */
package trafficsim.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.table.TableModel;
import trafficsim.model.EnvironmentModel;
import trafficsim.model.VehicleEventListener;
import trafficsim.model.VehicleEventType;
import trafficsim.model.VehicleState;

/**
 *
 * @author Adrian
 */
public class MainFrame extends javax.swing.JFrame {
    
    private final static String END_MESSAGE = "Simulation finished in %.2f seconds";
    private final static String STATE_RUNNING = "Running";
    private final static String STATE_FINISHED = "Finished";
    private static final int UPDATE_INTERVAL_MS = 100;
   
    private EnvironmentModel model;
    private Timer timer;
    
    private VehicleStateTableModel tableModel = new VehicleStateTableModel();
    
    /** Creates new form EnvironmentFrame */
    public MainFrame() {
        this.model = null;
        initComponents();
    }
    
    public MainFrame(EnvironmentModel model) {
        this.model = model;
        model.addVehicleEventListener(new VehicleEventListener() {
            @Override
            public void onVehicleEvent(VehicleEventType type, VehicleState state) {
                updateVehicleTable(type, state);
            }
        });
        
        initComponents();
        initCustom();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
        jLabel1 = new javax.swing.JLabel();
        simulationTimeTextField = new javax.swing.JTextField();
        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
        jLabel2 = new javax.swing.JLabel();
        vehicleCountTextField = new javax.swing.JTextField();
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
        jLabel3 = new javax.swing.JLabel();
        simulationStateTextField = new javax.swing.JTextField();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
        jScrollPane1 = new javax.swing.JScrollPane();
        vehicleTable = new javax.swing.JTable();
        filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5));
        jPanel2 = new javax.swing.JPanel();
        mapPanel1 = new trafficsim.ui.MapPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(1000, 600));

        jPanel1.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 5, 0, 5));
        jPanel1.setPreferredSize(new java.awt.Dimension(400, 600));
        jPanel1.setVerifyInputWhenFocusTarget(false);
        jPanel1.setLayout(new javax.swing.BoxLayout(jPanel1, javax.swing.BoxLayout.Y_AXIS));
        jPanel1.add(filler4);

        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel1.setText("Simulation time [seconds]");
        jLabel1.setMaximumSize(new java.awt.Dimension(2147483647, 14));
        jPanel1.add(jLabel1);

        simulationTimeTextField.setEditable(false);
        simulationTimeTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        simulationTimeTextField.setText("0");
        simulationTimeTextField.setMaximumSize(new java.awt.Dimension(2147483647, 20));
        simulationTimeTextField.setMinimumSize(new java.awt.Dimension(30, 20));
        simulationTimeTextField.setPreferredSize(new java.awt.Dimension(30, 20));
        jPanel1.add(simulationTimeTextField);
        jPanel1.add(filler3);

        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel2.setText("Remaining vehicles");
        jLabel2.setMaximumSize(new java.awt.Dimension(2147483647, 14));
        jPanel1.add(jLabel2);

        vehicleCountTextField.setEditable(false);
        vehicleCountTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        vehicleCountTextField.setText("0");
        vehicleCountTextField.setMaximumSize(new java.awt.Dimension(2147483647, 20));
        jPanel1.add(vehicleCountTextField);
        jPanel1.add(filler2);

        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
        jLabel3.setText("Simulation state");
        jLabel3.setMaximumSize(new java.awt.Dimension(2147483647, 14));
        jPanel1.add(jLabel3);

        simulationStateTextField.setEditable(false);
        simulationStateTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
        simulationStateTextField.setText("Running");
        simulationStateTextField.setMaximumSize(new java.awt.Dimension(2147483647, 20));
        jPanel1.add(simulationStateTextField);
        jPanel1.add(filler1);

        vehicleTable.setModel(tableModel);
        vehicleTable.setMaximumSize(new java.awt.Dimension(2147483647, 2147483647));
        jScrollPane1.setViewportView(vehicleTable);

        jPanel1.add(jScrollPane1);
        jPanel1.add(filler5);

        getContentPane().add(jPanel1, java.awt.BorderLayout.EAST);

        jPanel2.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 0));
        jPanel2.setLayout(new java.awt.BorderLayout());

        mapPanel1.setBackground(new java.awt.Color(0, 0, 0));
        mapPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0), 3));

        javax.swing.GroupLayout mapPanel1Layout = new javax.swing.GroupLayout(mapPanel1);
        mapPanel1.setLayout(mapPanel1Layout);
        mapPanel1Layout.setHorizontalGroup(
            mapPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 405, Short.MAX_VALUE)
        );
        mapPanel1Layout.setVerticalGroup(
            mapPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 484, Short.MAX_VALUE)
        );

        jPanel2.add(mapPanel1, java.awt.BorderLayout.CENTER);

        getContentPane().add(jPanel2, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler2;
    private javax.swing.Box.Filler filler3;
    private javax.swing.Box.Filler filler4;
    private javax.swing.Box.Filler filler5;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane jScrollPane1;
    private trafficsim.ui.MapPanel mapPanel1;
    private javax.swing.JTextField simulationStateTextField;
    private javax.swing.JTextField simulationTimeTextField;
    private javax.swing.JTextField vehicleCountTextField;
    private javax.swing.JTable vehicleTable;
    // End of variables declaration//GEN-END:variables

    private void initCustom() {
        mapPanel1.setModel(model);
        
        timer = new Timer(UPDATE_INTERVAL_MS, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                simulationStateTextField.setText(model.isSimulationFinished() ? STATE_FINISHED : STATE_RUNNING );
                simulationTimeTextField.setText(String.format("%.2f", model.getSimulationTime() / 1000.0));
                vehicleCountTextField.setText(String.valueOf(model.getVehicleCount()));
                mapPanel1.repaint();
            }
        });
        
        timer.setRepeats(true);
        timer.start();
    }

    public void ShowEndSimulationMessage() {
        String message = String.format(END_MESSAGE, model.getSimulationTime() / 1000.0);
        JOptionPane.showMessageDialog(this, message);
    }
    
    private void updateVehicleTable(final VehicleEventType type, VehicleState state) {
        
        final VehicleState stateCopy = state.clone();
        
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() { 
                tableModel.UpdateData(stateCopy);
            }
        });
    }
}
